#include <iostream>
#include <string>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include "Log.hpp"

class NoCopy
{
public:
    NoCopy(){}
    NoCopy(const NoCopy &) = delete;
    NoCopy &operator=(const NoCopy &) = delete;
};
class UdpServe : public NoCopy
{
private:
    int _sockfd;     // 套接字的文件描述符
    uint16_t _port;  // 端口
    std::string _ip = "0"; // ip: 12.34.56.78

public:
    UdpServe(uint16_t port)
        : _port(port)
    {
    }
    void usInit()
    {
        // 创建套接字
        _sockfd = socket(AF_INET, SOCK_DGRAM, 0);
        if (_sockfd < 0)
        {
            // 创建失败
            LOG(FATAL, "创建套接字失败\n");
            exit(1);
        }
        LOG(DEBUG, "创建套接字成功\n");
        // 绑定
        struct sockaddr_in local;
        memset(&local, 0, sizeof(local));
        local.sin_family = AF_INET;                     // 协议 ipv4、ipv6...
        local.sin_port = htons(_port);                  // 端口
        local.sin_addr.s_addr = inet_addr("0"); // ip: 需要的是4字节的ip，_ip不匹配，需要进行转换

        int n = ::bind(_sockfd, (struct sockaddr *)&local, sizeof(local));

        if (n < 0)
        {
            // 绑定失败
            LOG(FATAL, "绑定失败\n");
            exit(1);
        }
        LOG(DEBUG, "绑定成功\n");
    }
    void usStart()
    {
        LOG(DEBUG, "usStart");
        sockaddr_in client;
        memset(&client, 0, sizeof(client));
        socklen_t len = sizeof(client);
        while (true)
        {
            char message[1024] = {0};
            int n = recvfrom(_sockfd, message, sizeof(message) - 1, 0, (struct sockaddr *)&client, &len);
            if (n > 0)
            {
                message[n] = 0;
                LOG(DEBUG, "接收消息成功: %s\n", message);

                std::string echo_message = "[echo message] :";
                echo_message += message;
                sendto(_sockfd, echo_message.c_str(), echo_message.size(), 0, (struct sockaddr *)&client, len);
            }
            else
            {
                LOG(DEBUG, "接收消息失败\n");
            }
        }
    }
    ~UdpServe() 
    {
        if (_sockfd > 0)
            ::close(_sockfd);
    }
};